/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package analiseSintatica.Regras.Funcao;

import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSintatica.ErroSintaticoException;
import analiseSintatica.Regras.Blocos.RegraCorpoFuncao;
import analiseSintatica.Regras.DeclaracoesIniciais.RegraPrototipo;
import analiseSintatica.Regras.Regra;
import analiseSintatica.estruturadados.NoArvore;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Dede do Bem
 * 
 * <funcao> ::= <prototipo> <corpo_funcao>
 */
public class RegraFuncao extends Regra{

    protected static Regra instancia;

    protected String estrutura = "<prototipo> <corpo_funcao>";
    RegraPrototipo prototipo;
    RegraCorpoFuncao corpoFuncao;


    /**
     * Construtor privado necessario ao singleton
     */
    private RegraFuncao() {
    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     */
    public static RegraFuncao getInstance() {
        if (instancia == null) {
            instancia = new RegraFuncao();
        }
        return (RegraFuncao) instancia;
    }
    

    @Override
    public NoArvore analisar(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {

        ErroSintaticoException erros = new ErroSintaticoException();
        NoArvore NaoterminalFuncao = new NoArvore("<prototipo>", false);


        try{
            NaoterminalFuncao.adicionaFilho(RegraPrototipo.getInstance().analisar(listaTokens));
        }catch (ErroSintaticoException e){
            while(e.size() != 0)
                erros.addErros(e.getErros());
        }

        try{
            NaoterminalFuncao.adicionaFilho(RegraCorpoFuncao.getInstance().analisar(listaTokens));
        }catch (ErroSintaticoException e){
            while(e.size() != 0)
                erros.addErros(e.getErros());
        }


        return NaoterminalFuncao;
    }
    
  

    @Override
    protected void setPrimeiro() {
        //P<funcao> = P<prototipo>
        this.primeiro.add("identificador");
        this.primeiro.add("void");
        this.primeiro.add("char");
        this.primeiro.add("int");
        this.primeiro.add("float");
        this.primeiro.add("boolean");

        //throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    protected void setSeguinte() {
       /* S<funcao> = P<funcao> U S<decls_final>
          S<decls_final> = S<programa>
          S<programa> = {$}*/
        this.seguinte.add("identificador");
        this.seguinte.add("void");
        this.seguinte.add("char");
        this.seguinte.add("int");
        this.seguinte.add("float");
        this.seguinte.add("boolean");
        this.seguinte.add("$");

        //Adicionei a string vazia pq era pra adicionar Seguinte(programa), que nao existe.
                                    //É assim mesmo?! Estou em dúvida. - N eh vazio nao, eh $
        
    }

}
